package org.yookiee.support.core;

import com.google.common.base.Strings;
import org.yookiee.support.enums.DatePatternEnum;
import org.yookiee.support.toolkits.RegToolkit;

import java.text.DateFormatSymbols;
import java.text.FieldPosition;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Locale;

/**
 * FileName TimeZoneDateFormat
 * Package org.yookiee.support.core
 * Description
 * author cpstory
 * create 2023-11-15 13:44
 * version V1.0
 */
public class TimeZoneDateFormat extends SimpleDateFormat {

    public TimeZoneDateFormat() {
        super();
    }

    //默认为当前服务的区域
    private ZoneId zoneId = ZoneId.systemDefault();

    private String pattern;

    public TimeZoneDateFormat(String pattern) {
        super(pattern);
        this.pattern = pattern;
    }

    public TimeZoneDateFormat(String pattern, Locale locale) {
        super(pattern, locale);
        this.pattern = pattern;
    }

    public TimeZoneDateFormat(String pattern, DateFormatSymbols formatSymbols) {
        super(pattern, formatSymbols);
        this.pattern = pattern;
    }

    //这里处理时间可能会有问题，无法做到根据格式进行转换
    @Override
    public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition pos) {
        EasyLocale locale = I18NContext.get();
        //在微服务调用中，不需要对日期进行时区转换，避免多次序列化重复转换，只有入口和出口需要进行转换
        if(!"true".equals(locale.getCallService())){
            final String timezone = Strings.isNullOrEmpty(locale.getTimeZone()) ? DefaultTimeZone.defaultTimeZoneCode() : locale.getTimeZone();
            DateTimeFormatter formatString = DateTimeFormatter.ofPattern(this.pattern);
            return new StringBuffer(formatString.format(LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.of(timezone))));
        }
        final String timezone = DefaultTimeZone.defaultTimeZoneCode();
        DateTimeFormatter formatString = DateTimeFormatter.ofPattern(this.pattern);
        return new StringBuffer(formatString.format(LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.of(timezone))));
    }

    public String customFormat(Date date) {
        EasyLocale locale = I18NContext.get();
        final String timezone = Strings.isNullOrEmpty(locale.getTimeZone()) ? DefaultTimeZone.defaultTimeZoneCode() : locale.getTimeZone();
        DateTimeFormatter formatString = DateTimeFormatter.ofPattern(this.pattern);
        return new StringBuffer(formatString.format(LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.of(timezone)))).toString();
    }



    @Override
    public Date parse(String text) {
        EasyLocale locale = I18NContext.get();
        final String timezone = Strings.isNullOrEmpty(locale.getTimeZone()) ? DefaultTimeZone.defaultTimeZoneCode() : locale.getTimeZone();
        DateTimeFormatter formatString = null;
        LocalDateTime localDateTime = null;

        DatePatternEnum datePatternEnum = DatePatternEnum.format(this.pattern);

        if(datePatternEnum == null){
            return null;
        }
        switch (datePatternEnum){
            case YMD_HM:
            case YMD_HMS:
                formatString = DateTimeFormatter.ofPattern(datePatternEnum.getPattern());
                localDateTime = LocalDateTime.parse(text,formatString);
                break;
            case YMD:
                localDateTime = LocalDate.parse(text).atStartOfDay();
                break;
        }

        ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.of(timezone)).withZoneSameInstant(zoneId);
        return Date.from(zonedDateTime.toInstant());
    }

    @Override
    public Date parse(String text, ParsePosition pos) {
        EasyLocale locale = I18NContext.get();
        final String timezone = Strings.isNullOrEmpty(locale.getTimeZone()) ? DefaultTimeZone.defaultTimeZoneCode() : locale.getTimeZone();
        //把用户的时间转为系统时间
        DateTimeFormatter formatString = autoOfPatternToFormatter(text);
        if(formatString == null){
            return null;
        }
        LocalDateTime localDateTime = LocalDateTime.parse(text,formatString);
        ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.of(timezone)).withZoneSameInstant(zoneId);
        return Date.from(zonedDateTime.toInstant());
    }


    private DatePatternEnum autoOfPatternToPattern(String text){
        if(Strings.isNullOrEmpty(text)){
            return null;
        }

        for (DatePatternEnum datePatternEnum : DatePatternEnum.values()) {
            if (RegToolkit.verifyRule(text.trim(),datePatternEnum.getReg())) {
                return datePatternEnum;
            }
        }

        return null;
    }

    private DateTimeFormatter autoOfPatternToFormatter(String text){
        if(Strings.isNullOrEmpty(text)){
            return null;
        }

        for (DatePatternEnum datePatternEnum : DatePatternEnum.values()) {
            if (RegToolkit.verifyRule(text.trim(),datePatternEnum.getReg())) {
                return DateTimeFormatter.ofPattern(datePatternEnum.getPattern());
            }
        }
        return null;
    }
}
